using System;
using System.ComponentModel;
using System.ComponentModel.Design;
using System.Web.UI;
using System.Web.UI.Design;
using System.Web.UI.WebControls;

namespace PHSRAG.WebControls
{
	/// <summary>
	/// Provides a textbox for entering an email address, and includes functionality to validate whether the 
	/// email address is in a valid format, and if the field is required, provides functionality to validate
	/// whether an address has been supplied.
	/// </summary>
	[ToolboxData("<{0}:EmailAddress runat=\"server\"></{0}:EmailAddress>")]
	public class EmailAddress : System.Web.UI.WebControls.WebControl, INamingContainer
	{		
		private Label label;
		private TextBox email;

		private RegularExpressionValidator regExValidator;
		private RequiredFieldValidator requiredFieldValidator;

		private const string PromptKey = "emailPrompt_762D7A42-2A0A-4c4a-8235-6FB55FE29A3C";
		private const string RequiredKey = "emailRequired_762D7A42-2A0A-4c4a-8235-6FB55FE29A3C";

		/// <summary>If required, sets up a required field validator for the textbox</summary>
		[Category("Action"), Description("Causes the Email textbox to be invalid if no data is entered")]
		public bool Required
		{
			get { object o = ViewState[RequiredKey]; return (o == null) ? false : (bool)o; }
			set { ViewState[RequiredKey] = value; }
		}

		/// <summary>
		/// Gets/Sets the label that appears preceding the text box
		/// </summary>
		[Category("Appearance"), Description("Sets the label that precedes the text box")]
		public string Prompt
		{
			get { object o = ViewState[PromptKey]; return (o == null) ? "Email Address: " : (string)o; }
			set { ViewState[PromptKey] = value; }
		}

		/// <summary>
		/// The email address input by the user
		/// </summary>
		public string Email { get { EnsureChildControls(); return email.Text; } }

		/// <summary>
		/// Resets the textboxes' text to empty strings
		/// </summary>
		public void Reset() 
		{
			EnsureChildControls();
			email.Text = string.Empty;
		}

		#region Overrides

		/// <summary>
		/// Create all controls that will be in the EmailAddress. The creation is more than just instantiating
		/// the controls. It also involves generating the underlying HTML so that the controls shows up per the need.
		/// </summary>
		protected override void CreateChildControls()
		{
			Controls.Clear();

			label = new Label();
			label.ID = "label";
			label.Text = (Required) ? string.Format("*{0}", Prompt): Prompt;
			
			email = new TextBox();
			email.ID = "areaCode";

			CreateRegExValidators();
			if (Required) CreateRequiredFieldValidators();
			
			GenerateControlTree();
		}
		#endregion

		/// <summary>
		/// Creates the required field validator for the textbox
		/// </summary>
		private void CreateRequiredFieldValidators()
		{
			requiredFieldValidator = new RequiredFieldValidator();
			requiredFieldValidator.Display = ValidatorDisplay.None;
			requiredFieldValidator.ControlToValidate = email.ID;
			requiredFieldValidator.ErrorMessage = "Email address is required";
		}

		/// <summary>
		/// Creates the regular expression validator for the textbox
		/// </summary>
		private void CreateRegExValidators()
		{
			regExValidator = new RegularExpressionValidator();
			regExValidator.Display = ValidatorDisplay.None;
			regExValidator.ValidationExpression = @"^[^@]+@[^.@]+[.][^@]+$";
			regExValidator.ControlToValidate = email.ID;
			regExValidator.ErrorMessage = "Please enter a valid email address";
		}

		/// <summary>
		/// Setup the control tree to reflect the actual (and exact) layout of the controls within the Email Address.
		/// </summary>
		private void GenerateControlTree()
		{
			Table table = new Table();
			Controls.Add(table);

			TableRow row = new TableRow();
			table.Rows.Add(row);

			TableCell c1 = new TableCell();
			c1.Controls.Add(label);
			row.Cells.Add(c1);

			TableCell c2 = new TableCell();
			c2.Controls.Add(email);
			row.Cells.Add(c2);			

			TableCell c3 = new TableCell();
			c3.Controls.Add(regExValidator);

			if (Required)
				c3.Controls.Add(requiredFieldValidator);

			row.Cells.Add(c3);
		}

		#region Internal Methods
		/// <summary>
		/// This method is ONLY invoked by the associated designer to show the control contents at design time.
		/// </summary>
		internal void Design()
		{
			EnsureChildControls();
		}
		#endregion

		#region Class EmailAddressDesigner
		/// <summary>
		/// Designer associated with the EmailAddress control.
		/// </summary>
		/// <remarks>
		/// This class cannot be used directly.
		/// </remarks>
		public class EmailAddressDesigner : ControlDesigner
		{
			#region Overrides
			/// <summary>
			/// Force the EmailAddress control to create its child controls for display at design time.
			/// </summary>
			/// <returns>HTML representation of the EmailAddress control</returns>
			public override string GetDesignTimeHtml()
			{
				((EmailAddress)Component).Design();
				return base.GetDesignTimeHtml();
			}
			#endregion
		}
		#endregion
	}
}
